﻿using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;

namespace Sage.Data.Extensions
{
    /// <summary>
    /// JsonNode 扩展方法，提供对象或空数组的转换功能
    /// </summary>
    public static class JsonNodeExtensions
    {
        /// <summary>
        /// 将JsonNode转换为对象，如果是空数组则返回null
        /// </summary>
        /// <typeparam name="T">目标对象类型</typeparam>
        /// <param name="node">要转换的JsonNode</param>
        /// <param name="typeInfo">JSON类型信息</param>
        /// <returns>转换后的对象，如果是空数组或无效数据则返回null</returns>
        public static T? ToObjectOrNull<T>(this JsonNode? node, JsonTypeInfo<T> typeInfo) where T : class
        {
            ArgumentNullException.ThrowIfNull(typeInfo);

            return node switch
            {
                null => null,
                JsonArray array when array.Count == 0 => null,
                JsonObject => node.Deserialize(typeInfo),
                _ => null
            };
        }

        /// <summary>
        /// 将JsonNode转换为对象，如果是空数组则返回null
        /// </summary>
        /// <typeparam name="T">目标对象类型</typeparam>
        /// <param name="node">要转换的JsonNode</param>
        /// <param name="context">JSON序列化上下文</param>
        /// <returns>转换后的对象，如果是空数组或无效数据则返回null</returns>
        /// <exception cref="ArgumentNullException">当context为null时抛出</exception>
        /// <exception cref="InvalidOperationException">当无法获取类型信息时抛出</exception>
        public static T? ToObjectOrNull<T>(this JsonNode? node, JsonSerializerContext context) where T : class
        {
            ArgumentNullException.ThrowIfNull(context);

            var typeInfo = context.GetTypeInfo(typeof(T)) as JsonTypeInfo<T>
                ?? throw new InvalidOperationException($"无法从上下文中获取类型 {typeof(T).Name} 的类型信息，请确保类型已在JsonSerializerContext中注册");

            return node.ToObjectOrNull(typeInfo);
        }

        /// <summary>
        /// 安全地将JsonNode转换为对象，如果是空数组则返回null，任何异常都返回null
        /// </summary>
        /// <typeparam name="T">目标对象类型</typeparam>
        /// <param name="node">要转换的JsonNode</param>
        /// <param name="typeInfo">JSON类型信息</param>
        /// <returns>转换后的对象，如果是空数组、无效数据或转换失败则返回null</returns>
        public static T? SafeToObjectOrNull<T>(this JsonNode? node, JsonTypeInfo<T>? typeInfo) where T : class
        {
            if (typeInfo == null)
                return null;

            try
            {
                return node.ToObjectOrNull(typeInfo);
            }
            catch
            {
                return null;
            }
        }
    }
}
